﻿using System;
using System.Collections.Generic;
using SlimDX;
using RGeos.Framework.OTL.Interface;
using RGeos.SlimScene.Core;
using RGeos.Basic;
using RGeos.Framework.OTL.Renderable;

namespace RGeos.Framework.OTL
{
    /// <summary>
    /// 塔位点
    /// </summary>
    public class OtlTowerPoint : ITowerPosition, IRenderable
    {
        public string ID { get; set; }//序号

        public string TaNumber { get; set; }//塔号

        public string TowerStyle { get; set; }//塔型

        //塔的位置
        public Vector3 Position { get; set; }

        //架空线路挂点信息
        public IOTLHangPoints HangPoints { get; set; }

        public ITowerSymbol TowerSymbol { get; set; }
        //地挂点信息
        // public IOTLHangPoints WireGroundHangPoints { get; set; }

        //导挂点信息
        //public IOTLHangPoints WireHangPoints { get; set; }

        //跳挂点信息
        //public IOTLHangPoints JumpHangPoints { get; set; }

        //放置何种类型的塔
        public RgHangPointTowerTypes HangPointTowerType { get; set; }

        private OtlDang mPreDang;

        public OtlDang PreDang
        {
            get { return mPreDang; }
            set { mPreDang = value; }
        }

        private OtlDang mNextDang;

        public OtlDang NextDang
        {
            get { return mNextDang; }
            set { mNextDang = value; }
        }
        //水平档距
        public double HorizonSpan
        {
            get
            {
                if (mPreDang != null && mNextDang != null)
                {
                    return (mPreDang.Distance + mNextDang.Distance) / 2;
                }
                return 0;
            }
        }
        //转角,统一以度表示
        double mCornerAngle = -1;
        public double CornerAngle
        {
            get
            {
                if (mCornerAngle == -1)
                {
                    return GetCornerAngle();
                }
                else
                {
                    return mCornerAngle;
                }
            }
            set
            {
                mCornerAngle = value;
            }
        }

        public double GetCornerAngle()
        {
            if (mPreDang == null)
            {
                return 0;
            }
            if (mNextDang == null)
            {
                return 0;
            }
            if (mPreDang != null && mNextDang != null)
            {
                Vector3 pre = this.PreDang.FirstTower.Position;
                Vector3 current = Position;
                Vector3 next = this.NextDang.SecondTower.Position;
                Vector3 preV = current - pre;
                Vector3 nextV = next - current;
                preV.Z = 0;
                nextV.Z = 0;
                double angle = Vector3.Dot(preV, nextV) / Vector3.Dot(preV, preV) / Vector3.Dot(nextV, nextV);
                return Math.Acos(angle);
            }
            return 0;
        }

        public Vector3 GetForwardDirection()
        {
            if (mPreDang == null && mNextDang != null)
            {
                Vector3 current = Position;
                Vector3 next = this.NextDang.SecondTower.Position;
                return GetDirection(Vector3.Zero, current, next);
            }
            if (mPreDang != null && mNextDang == null)
            {
                Vector3 pre = this.PreDang.FirstTower.Position;
                Vector3 current = Position;
                return GetDirection(pre, current, Vector3.Zero);
            }
            if (mPreDang != null && mNextDang != null)
            {
                Vector3 pre = this.PreDang.FirstTower.Position;
                Vector3 current = Position;
                Vector3 next = this.NextDang.SecondTower.Position;
                return GetDirection(pre, current, next);
            }
            return Vector3.Zero;
        }

        public List<IHangPoint> GetWireGroundHangPoints()
        {
            List<IHangPoint> towerHangPts = this.HangPoints.GetHangPoints((int)RgWireStyles.WireGround, (int)RgIsForward.NotDefine);
            if (towerHangPts != null && towerHangPts.Count > 0)
            {
                List<IHangPoint> TowerPlusInsulator = new List<IHangPoint>();
                for (int i = 0; i < towerHangPts.Count; i++)
                {
                    IHangPoint tempHangPt = towerHangPts[i].GetAssembleHangPoint();
                    TowerPlusInsulator.Add(tempHangPt);
                }
                return TowerPlusInsulator;
            }
            return towerHangPts;
        }
        public List<IHangPoint> GetWireFrontHangPoints()
        {
            List<IHangPoint> towerHangPts = null;
            if (this.HangPointTowerType == RgHangPointTowerTypes.Z)
            {
                towerHangPts = this.HangPoints.GetHangPoints((int)RgWireStyles.Wire, (int)RgIsForward.NotDefine);
            }
            else
            {
                towerHangPts = this.HangPoints.GetHangPoints((int)RgWireStyles.Wire, (int)RgIsForward.Front);
            }
            if (towerHangPts != null && towerHangPts.Count > 0)
            {
                List<IHangPoint> TowerPlusInsulator = new List<IHangPoint>();
                for (int i = 0; i < towerHangPts.Count; i++)
                {
                    IHangPoint tempHangPt = towerHangPts[i].GetAssembleHangPoint();
                    TowerPlusInsulator.Add(tempHangPt);
                }
                return TowerPlusInsulator;
            }
            return towerHangPts;
        }
        public List<IHangPoint> GetWireBackHangPoints()
        {
            List<IHangPoint> towerHangPts = null;
            if (this.HangPointTowerType == RgHangPointTowerTypes.Z)
            {
                towerHangPts = this.HangPoints.GetHangPoints((int)RgWireStyles.Wire, (int)RgIsForward.NotDefine);
            }
            else
            {
                towerHangPts = this.HangPoints.GetHangPoints((int)RgWireStyles.Wire, (int)RgIsForward.Back);
            }
            if (towerHangPts != null && towerHangPts.Count > 0)
            {
                List<IHangPoint> TowerPlusInsulator = new List<IHangPoint>();
                for (int i = 0; i < towerHangPts.Count; i++)
                {
                    IHangPoint tempHangPt = towerHangPts[i].GetAssembleHangPoint();
                    TowerPlusInsulator.Add(tempHangPt);
                }
                return TowerPlusInsulator;
            }
            return towerHangPts;
        }
        /// <summary>
        /// 获取某类型导线，某一侧的挂点,剔除了绝缘子串的挂点坐标
        /// </summary>
        /// <param name="hangType">电力线类型</param>
        /// <param name="forward">大号侧？小号侧</param>
        /// <returns></returns>
        public List<IHangPoint> GetHangPoints(int hangType, int forward)
        {
            List<IHangPoint> towerHangPts = this.HangPoints.GetHangPoints(hangType, forward);
            if (towerHangPts != null && towerHangPts.Count > 0)
            {
                List<IHangPoint> TowerPlusInsulator = new List<IHangPoint>();
                for (int i = 0; i < towerHangPts.Count; i++)
                {
                    IHangPoint tempHangPt = towerHangPts[i].GetAssembleHangPoint();
                    TowerPlusInsulator.Add(tempHangPt);
                }
                return TowerPlusInsulator;
            }
            return towerHangPts;
        }

        //计算前视方向向量
        public static Vector3 GetDirection(Vector3 Pre, Vector3 Current, Vector3 Next)
        {
            Vector3 direction = new Vector3();
            if (Pre == Vector3.Zero  && Next != Vector3.Zero)
            {
                direction = Next - Current;
            }
            if (Pre != Vector3.Zero  && Next != Vector3.Zero)
            {
                Vector3 VerticalForward = BisectorForward(Pre, Current, Next, 30);//垂直角分线的线路前视方向上距离30m的点
                direction = VerticalForward - Current;
            }
            if (Pre != Vector3.Zero  && Next == Vector3.Zero)
            {
                direction = Pre - Current;
            }
            return direction;
        }

        /// <summary>
        /// 前向垂直角分线的点
        /// </summary>
        /// <param name="V0"></param>
        /// <param name="V1"></param>
        /// <param name="V2"></param>
        /// <param name="dLength"></param>
        /// <returns></returns>
        public static Vector3 BisectorForward(Vector3 V0, Vector3 V1, Vector3 V2, double dLength)
        {
            //通过象限角来求中平分线
            double dJ2 = RgMath.GetQuadrantAngle(V2.X - V1.X, V2.Y - V1.Y);//第二条线的象限角
            double dJ1 = RgMath.GetQuadrantAngle(V1.X - V0.X, V1.Y - V0.Y);//第一条线的象限角
            double dJ = 0.0;//中分线的象限角
            int bLeft = RgMath.isLeft(V0, V1, V2);
            double dJZ = RgMath.GetIncludedAngle(V0, V1, V2);//计算夹角
            dJZ = Math.PI - dJZ;
            if (bLeft > 0)
            {
                dJ = dJ2 + dJZ / 2 - Math.PI / 2;
                if (dJ < 0)
                    dJ = 2 * Math.PI + dJ;
                if (dJ > 2 * Math.PI)
                    dJ = dJ - 2 * Math.PI;
            }
            else
            {
                dJ = dJ2 - dJZ / 2 + Math.PI / 2;
                if (dJ < 0)
                    dJ = 2 * Math.PI + dJ;
                if (dJ > 2 * Math.PI)
                    dJ = dJ - 2 * Math.PI;
            }
            double dx = dLength * Math.Cos(dJ);
            double dy = dLength * Math.Sin(dJ);
            Vector3 res = new Vector3();
            res.X = (float)(V1.X + dx);
            res.Y = (float)(V1.Y + dy);
            return res;
        }


        public bool IsOn = true;
        public bool IsInitialize = false;

        public void Initialize(DrawArgs drawArgs)
        {
            if (IsOn && !IsInitialize)
            {
                //渲染塔位点，包括模型
                if (TowerSymbol != null)
                {
                    TowerSymbol.Initialize(drawArgs);
                }
                IsInitialize = true;
            }
        }

        public void Update(DrawArgs drawArgs)
        {
            if (TowerSymbol != null)
            {
                TowerSymbol.Update(drawArgs);
            }
        }

        public void Render(DrawArgs drawArgs)
        {
            if (IsOn && IsInitialize)
            {
                if (TowerSymbol != null)
                {
                    TowerSymbol.Render(drawArgs);
                }
            }
        }

        public void Dispose()
        {
            if (TowerSymbol != null)
            {
                TowerSymbol.Dispose();
            }
            IsInitialize = false;
        }
    }
}
